home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / gplt_x11.c < prev    next >
C/C++ Source or Header  |  1993-09-15  |  31KB  |  984 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: gplt_x11.c%v 3.50.1.9 1993/08/05 05:38:59 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /*-----------------------------------------------------------------------------
  7.  *   gnuplot_x11 - X11 outboard terminal driver for gnuplot 3.3
  8.  *
  9.  *   Requires installation of companion inboard x11 driver in gnuplot/term.c
  10.  *
  11.  *   Acknowledgements: 
  12.  *      Chris Peterson (MIT)
  13.  *      Dana Chee (Bellcore) 
  14.  *      Arthur Smith (Cornell)
  15.  *      Hendri Hondorp (University of Twente, The Netherlands)
  16.  *      Bill Kucharski (Solbourne)
  17.  *      Charlie Kline (University of Illinois)
  18.  *      Yehavi Bourvine (Hebrew University of Jerusalem, Israel)
  19.  *      Russell Lang (Monash University, Australia)
  20.  *      O'Reilly & Associates: X Window System - Volumes 1 & 2
  21.  *
  22.  *   This code is provided as is and with no warranties of any kind.
  23.  *       
  24.  * There is a mailing list for gnuplot users. Note, however, that the
  25.  * newsgroup 
  26.  *    comp.graphics.gnuplot 
  27.  * is identical to the mailing list (they
  28.  * both carry the same set of messages). We prefer that you read the
  29.  * messages through that newsgroup, to subscribing to the mailing list.
  30.  * (If you can read that newsgroup, and are already on the mailing list,
  31.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  32.  * removed from the mailing list.)
  33.  *
  34.  * The address for mailing to list members is
  35.  *       info-gnuplot@dartmouth.edu
  36.  * and for mailing administrative requests is 
  37.  *       info-gnuplot-request@dartmouth.edu
  38.  * The mailing list for bug reports is 
  39.  *       bug-gnuplot@dartmouth.edu
  40.  * The list of those interested in beta-test versions is
  41.  *       info-gnuplot-beta@dartmouth.edu
  42.  *---------------------------------------------------------------------------*/
  43.  
  44. #define DEFAULT_X11
  45. #if defined(VMS) || defined(CRIPPLED_SELECT)
  46. #undef DEFAULT_X11
  47. #endif
  48. #if defined(VMS) && defined(CRIPPLED_SELECT)
  49. Error. Incompatible options.
  50. #endif
  51.  
  52. #include <X11/Xos.h>
  53. #include <X11/Xlib.h>
  54. #include <X11/Xutil.h>
  55. #include <X11/Xatom.h>
  56. #include <X11/Xresource.h>
  57.  
  58. #include <stdio.h>
  59. #include <signal.h>
  60.  
  61. #ifdef BSD_TYPES
  62. #include <sys/bsdtypes.h>
  63. #endif /* BSD_TYPES */
  64.  
  65. #if !defined(VMS) && !defined(FD_SET) && !defined(OLD_SELECT)
  66. #include <sys/select.h>
  67. #endif /* !VMS && !FD_SET && !OLD_SELECT */
  68.  
  69. #ifndef FD_SET
  70.  
  71. #define FD_SET(n, p)    ((p)->fds_bits[0] |= (1 << ((n) % 32)))
  72. #define FD_CLR(n, p)    ((p)->fds_bits[0] &= ~(1 << ((n) % 32)))
  73. #define FD_ISSET(n, p)  ((p)->fds_bits[0] & (1 << ((n) % 32)))
  74. #define FD_ZERO(p)      bzero((char *)(p), sizeof(*(p)))
  75.  
  76. #endif /* !FD_SET */
  77.  
  78. #ifdef SOLARIS
  79. #include <sys/systeminfo.h>
  80. #endif /* SOLARIS */
  81.  
  82.  
  83. #include <errno.h>
  84. extern int errno;
  85.  
  86. #define FallbackFont "fixed"
  87.  
  88. #define Ncolors 13
  89. unsigned long colors[Ncolors];
  90.  
  91. #define Nwidths 10
  92. unsigned int widths[Nwidths] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  93.  
  94. #define Ndashes 10
  95. char dashes[Ndashes][5];
  96.  
  97. Display *dpy; int scr; Window win, root;
  98. Visual *vis; GC gc = (GC)0; Pixmap pixmap; XFontStruct *font;
  99. unsigned int W = 640, H = 450; int D, gX = 100, gY = 100;
  100. unsigned int BorderWidth = 2;
  101. unsigned User_Size = 0, User_Position = 0; /* User specified? */
  102.  
  103.  
  104. Bool Mono = 0, Gray = 0, Rv = 0, Clear = 0;
  105. char Name[64] = "gnuplot";
  106. char Class[64] = "Gnuplot";
  107.  
  108. int cx=0, cy=0, vchar, nc = 0, ncalloc = 0;
  109. double xscale, yscale, pointsize;
  110. #define X(x) (int) (x * xscale)
  111. #define Y(y) (int) ((4095-y) * yscale)
  112. enum JUSTIFY { LEFT, CENTRE, RIGHT } jmode;
  113.  
  114. #define Nbuf 1024
  115. char buf[Nbuf], **commands = (char **)0;
  116.  
  117. FILE *X11_ipc;
  118. char X11_ipcpath[32];
  119.  
  120.  
  121. /*-----------------------------------------------------------------------------
  122.  *   main program 
  123.  *---------------------------------------------------------------------------*/
  124.  
  125. main(argc, argv) int argc; char *argv[]; {
  126.  
  127.    preset(argc, argv);
  128.    mainloop();
  129.    exit(0);
  130.  
  131.    }
  132.  
  133. /*-----------------------------------------------------------------------------
  134.  *   mainloop processing - process X events and input from gnuplot
  135.  *
  136.  *   Three different versions of main loop processing are provided to support
  137.  *   three different platforms.
  138.  * 
  139.  *   DEFAULT_X11:     use select() for both X events and input on stdin 
  140.  *                    from gnuplot inboard driver
  141.  *
  142.  *   CRIPPLED_SELECT: use select() to service X events and check during 
  143.  *                    select timeout for temporary plot file created
  144.  *                    by inboard driver
  145.  *
  146.  *   VMS:             use XNextEvent to service X events and AST to
  147.  *                    service input from gnuplot inboard driver on stdin 
  148.  *---------------------------------------------------------------------------*/
  149.  
  150.  
  151. #ifdef DEFAULT_X11
  152. /*-----------------------------------------------------------------------------
  153.  *    DEFAULT_X11 mainloop
  154.  *---------------------------------------------------------------------------*/
  155.  
  156. mainloop() {
  157.    int nf, nfds, cn = ConnectionNumber(dpy), in = fileno(stdin);
  158.    struct timeval timeout, *timer = (struct timeval *)0;
  159.    fd_set rset, tset;
  160.    unsigned long all = 0xffffffff;
  161.    XEvent xe;
  162.  
  163.    X11_ipc = stdin;
  164.  
  165.    FD_ZERO(&rset);
  166.    FD_SET(cn, &rset);
  167.  
  168.    FD_SET(in, &rset);
  169.    nfds = (cn > in) ? cn + 1 : in + 1;
  170.  
  171. #ifdef ISC22
  172. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  173.    timeout.tv_sec  = 0;        /* select() in ISC2.2 needs timeout */
  174.    timeout.tv_usec = 300000;    /* otherwise input from gnuplot is */
  175.    timer = &timeout;        /* suspended til next X event. */
  176. #endif /* ISC22      (0.3s are short enough not to be noticed */
  177.  
  178.    while(1) {
  179.       tset = rset;
  180.       nf = select(nfds, &tset, (fd_set *)0, (fd_set *)0, timer);
  181.       if (nf < 0) {
  182.      if (errno == EINTR) continue;
  183.      fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
  184.      exit(1);
  185.      }
  186.       nf > 0 && XNoOp(dpy);
  187.       if (FD_ISSET(cn, &tset)) {
  188.      while (XCheckMaskEvent(dpy, all, &xe)) {
  189.         (xe.type == ConfigureNotify)  && resize(&xe); 
  190.         }
  191.      }
  192.       FD_ISSET(in, &tset) && record();
  193.       }
  194.    }
  195.  
  196. #endif
  197.  
  198.  
  199. #ifdef CRIPPLED_SELECT
  200. /*-----------------------------------------------------------------------------
  201.  *    CRIPPLED_SELECT mainloop
  202.  *---------------------------------------------------------------------------*/
  203.  
  204. mainloop() {
  205.    int nf, nfds, cn = ConnectionNumber(dpy);
  206.    struct timeval timeout, *timer;
  207.    fd_set rset, tset;
  208.    unsigned long all = 0xffffffff;
  209.    XEvent xe;
  210.  
  211.    FD_ZERO(&rset);
  212.    FD_SET(cn, &rset);
  213.  
  214.    timeout.tv_sec = 1;
  215.    timeout.tv_usec = 0;
  216.    timer = &timeout;
  217.    sprintf(X11_ipcpath, "/tmp/Gnuplot_%d", getppid());
  218.    nfds = cn + 1;
  219.  
  220.    while(1) {
  221.       tset = rset;
  222.       nf = select(nfds, &tset, (fd_set *)0, (fd_set *)0, timer);
  223.       if (nf < 0) {
  224.      if (errno == EINTR) continue;
  225.      fprintf(stderr, "gnuplot: select failed. errno:%d\n", errno);
  226.      exit(1);
  227.      }
  228.       nf > 0 && XNoOp(dpy);
  229.       if (FD_ISSET(cn, &tset)) {
  230.      while (XCheckMaskEvent(dpy, all, &xe)) {
  231.         (xe.type == ConfigureNotify)  && resize(&xe); 
  232.         }
  233.      }
  234.       if ((X11_ipc = fopen(X11_ipcpath, "r"))) {
  235.      unlink(X11_ipcpath);
  236.      record();
  237.      fclose(X11_ipc);
  238.      }
  239.       }
  240.    }
  241. #endif /* CRIPPLED_SELECT */
  242.  
  243.  
  244. #ifdef VMS
  245. /*-----------------------------------------------------------------------------
  246.  *    VMS mainloop - Yehavi Bourvine - YEHAVI@VMS.HUJI.AC.IL
  247.  *---------------------------------------------------------------------------*/
  248.  
  249. /*  In VMS there is no decent Select(). hence, we have to loop inside
  250.  *  XGetNextEvent for getting the next X window event. In order to get input
  251.  *  from the master we assign a channel to SYS$INPUT and use AST's in order to
  252.  *  receive data. */
  253.  
  254. #include <iodef.h>
  255. char    STDIIN[] = "SYS$INPUT:";
  256. short   STDIINchannel, STDIINiosb[4];
  257. struct  { short size, type; char  *address; } STDIINdesc;
  258. char    STDIINbuffer[64];
  259. int     status;
  260.  
  261.  
  262. mainloop() {
  263.    XEvent xe;
  264.  
  265.    STDIINdesc.size = strlen(STDIIN); 
  266.    STDIINdesc.type = 0;
  267.    STDIINdesc.address = STDIIN;
  268.    status = sys$assign(&STDIINdesc, &STDIINchannel, 0, 0, 0);
  269.    if((status & 0x1) == 0)  exit(status); 
  270.    ast();
  271.  
  272.    for(;;) {
  273.       XNextEvent(dpy, &xe);
  274.       (xe.type == ConfigureNotify)  && resize(&xe); 
  275.       }
  276.    }
  277.  
  278. ast() {
  279.    int record();
  280.    int status = sys$qio(0, STDIINchannel, IO$_READVBLK, STDIINiosb, record,
  281.                 0, STDIINbuffer, sizeof(STDIINbuffer) -1,0, 0, 0, 0);
  282.    if((status & 0x1) == 0) exit(status);
  283.    }
  284. #endif /* VMS */
  285.  
  286.  
  287. #ifndef VMS
  288. /*-----------------------------------------------------------------------------
  289.  *   record - record new plot from gnuplot inboard X11 driver (Unix)
  290.  *---------------------------------------------------------------------------*/
  291.  
  292. record() {
  293.  
  294.    while (fgets(buf, Nbuf, X11_ipc)) {
  295.      if (*buf == 'G') {                           /* enter graphics mode */
  296.      if (commands) {
  297.         int n; for (n=0; n<nc; n++) free(commands[n]);
  298.         free(commands);
  299.         }
  300.      commands = (char **)0; nc = ncalloc = 0;
  301.          }
  302.       else if (*buf == 'E') { display(); break; } /* leave graphics mode */
  303.       else if (*buf == 'R') { exit(0); }          /* leave X11/x11 mode  */
  304.       else {                                      /* record command      */
  305.      char *p;
  306.      if (nc >= ncalloc) {
  307.         ncalloc = ncalloc*2 + 1;
  308.         commands = (commands)
  309.            ? (char **)realloc(commands, ncalloc * sizeof(char *))
  310.            : (char **)malloc(sizeof(char *));
  311.         }
  312.      p = (char *)malloc((unsigned)strlen(buf)+1);
  313.      if (!commands || !p) {
  314.         fprintf(stderr, "gnuplot: can't get memory. X11 aborted.\n");
  315.         exit(1);
  316.         }
  317.      commands[nc++] = strcpy(p, buf);
  318.      }
  319.       }
  320.    if (feof(X11_ipc) || ferror(X11_ipc)) exit(1);
  321.    }
  322.  
  323. #else    /* VMS */
  324. /*-----------------------------------------------------------------------------
  325.  *   record - record new plot from gnuplot inboard X11 driver (VMS)
  326.  *---------------------------------------------------------------------------*/
  327.  
  328. record() {
  329.    int    status;
  330.  
  331.    if((STDIINiosb[0] & 0x1) == 0) exit(STDIINiosb[0]);
  332.    STDIINbuffer[STDIINiosb[1]] = '\0';
  333.    strcpy(buf, STDIINbuffer);
  334.  
  335.    if (*buf == 'G') {                           /* enter graphics mode */
  336.       if (commands) {
  337.          int n; for (n=0; n<nc; n++) free(commands[n]);
  338.          free(commands);
  339.          }
  340.        commands = (char **)0; nc = ncalloc = 0;
  341.        }
  342.    else if (*buf == 'E') {                      /* leave graphics mode */
  343.       display(); 
  344.       }
  345.    else if (*buf == 'R') {                      /* leave x11/X11 mode  */
  346.        sys$cancel(STDIINchannel);
  347.        XCloseDisplay(dpy);
  348.        sys$delprc(0,0);      /* Somehow it doesn't drop itself... */
  349.        exit(1); 
  350.        }
  351.    else {                                       /* record command      */
  352.       char *p;
  353.       if (nc >= ncalloc) {
  354.      ncalloc = ncalloc*2 + 1;
  355.      commands = (commands)
  356.         ? (char **)realloc(commands, ncalloc * sizeof(char *))
  357.         : (char **)malloc(sizeof(char *));
  358.      }
  359.       p = (char *)malloc((unsigned)strlen(buf)+1);
  360.       if (!commands || !p) {
  361.      fprintf(stderr, "gnuplot: can't get memory. X11 aborted.\n");
  362.      exit(1);
  363.      }
  364.       commands[nc++] = strcpy(p, buf);
  365.       }
  366.    ast();
  367.    }
  368. #endif /* VMS */
  369.  
  370. /*-----------------------------------------------------------------------------
  371.  *   display - display last plot from gnuplot inboard X11 driver
  372.  *---------------------------------------------------------------------------*/
  373.  
  374. display() {
  375.    int n, x, y, sw, sl, lt, width, type, point, px, py;
  376.    char *buf, *str;
  377.  
  378.    if (!nc) return;
  379.  
  380.    /* set scaling factor between internal driver & window geometry */
  381.    xscale = (double)W / 4096.;  yscale = (double)H / 4096.;  
  382.  
  383.    /* create new pixmap & GC */
  384.    if (gc) { XFreeGC(dpy, gc); XFreePixmap(dpy, pixmap); }
  385.    pixmap = XCreatePixmap(dpy, root, W, H, D);
  386.    gc = XCreateGC(dpy, pixmap, 0, (XGCValues *)0);
  387.    XSetFont(dpy, gc, font->fid);
  388.  
  389.    /* set pixmap background */
  390.    XSetForeground(dpy, gc, colors[0]);
  391.    XFillRectangle(dpy, pixmap, gc, 0, 0, W, H);
  392.    XSetBackground(dpy, gc, colors[0]);
  393.  
  394.    /* set new pixmap as window background */
  395.    XSetWindowBackgroundPixmap(dpy, win, pixmap);
  396.  
  397.    /* top the window but don't put keyboard or mouse focus into it. */
  398.    XMapRaised(dpy, win);
  399.  
  400.    /* momentarily clear the window first if requested */
  401.    if (Clear) {
  402.       XClearWindow(dpy, win);
  403.       XFlush(dpy);
  404.       }
  405.  
  406.    /* loop over accumulated commands from inboard driver */
  407.    for (n=0; n<nc; n++) {
  408.       buf = commands[n];
  409.  
  410.       /*   X11_vector(x,y) - draw vector  */
  411.       if (*buf == 'V') { 
  412.      sscanf(buf, "V%4d%4d", &x, &y);  
  413.      XDrawLine(dpy, pixmap, gc, X(cx), Y(cy), X(x), Y(y));
  414.      cx = x; cy = y;
  415.      }
  416.  
  417.       /*   X11_move(x,y) - move  */
  418.       else if (*buf == 'M') 
  419.      sscanf(buf, "M%4d%4d", &cx, &cy);  
  420.  
  421.       /*   X11_put_text(x,y,str) - draw text   */
  422.       else if (*buf == 'T') { 
  423.      sscanf(buf, "T%4d%4d", &x, &y);  
  424.      str = buf + 9; sl = strlen(str) - 1;
  425.      sw = XTextWidth(font, str, sl);
  426.      switch(jmode) {
  427.         case LEFT:   sw = 0;     break;
  428.         case CENTRE: sw = -sw/2; break;
  429.         case RIGHT:  sw = -sw;   break;
  430.         }
  431.      XSetForeground(dpy, gc, colors[2]);
  432.      XDrawString(dpy, pixmap, gc, X(x)+sw, Y(y)+vchar/3, str, sl);
  433.      XSetForeground(dpy, gc, colors[lt+3]);
  434.      }
  435.  
  436.       /*   X11_justify_text(mode) - set text justification mode  */
  437.       else if (*buf == 'J') 
  438.      sscanf(buf, "J%4d", &jmode);
  439.  
  440.       /*   X11_linetype(type) - set line type  */
  441.       else if (*buf == 'L') { 
  442.      sscanf(buf, "L%4d", <);
  443.      lt = (lt%8)+2;
  444.      width = widths[lt];
  445.      if (dashes[lt][0]) {
  446.         type = LineOnOffDash;
  447.         XSetDashes(dpy, gc, 0, dashes[lt], strlen(dashes[lt]));
  448.         }
  449.      else {
  450.         type = LineSolid;
  451.         }
  452.      XSetForeground(dpy, gc, colors[lt+3]);
  453.      XSetLineAttributes( dpy,gc, width, type, CapButt, JoinBevel);
  454.        }
  455.  
  456.       /*   X11_point(number) - draw a point */
  457.       else if (*buf == 'P') { 
  458.       sscanf(buf, "P%1d%4d%4d", &point, &x, &y);  
  459.       if (point==7) {
  460.          /* set point size */
  461.          px = (int) (x * xscale * pointsize);
  462.          py = (int) (y * yscale * pointsize);
  463.          }
  464.       else {
  465.         if (type != LineSolid || width != 0) {  /* select solid line */
  466.            XSetLineAttributes(dpy, gc, 0, LineSolid, CapButt, JoinBevel);
  467.            }
  468.         switch(point) {
  469.            case 0: /* dot */
  470.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  471.            break;
  472.            case 1: /* do diamond */ 
  473.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x), Y(y)-py);
  474.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x)+px, Y(y));
  475.            XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y), X(x), Y(y)+py);
  476.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)+py, X(x)-px, Y(y));
  477.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  478.            break;
  479.            case 2: /* do plus */ 
  480.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x)+px, Y(y));
  481.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x), Y(y)+py);
  482.            break;
  483.            case 3: /* do box */ 
  484.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)-py);
  485.            XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y)-py, X(x)+px, Y(y)+py);
  486.            XDrawLine(dpy,pixmap,gc, X(x)+px, Y(y)+py, X(x)-px, Y(y)+py);
  487.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)-px, Y(y)-py);
  488.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  489.            break;
  490.            case 4: /* do X */ 
  491.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)+py);
  492.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)+px, Y(y)-py);
  493.            break;
  494.            case 5: /* do triangle */ 
  495.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-(4*px/3), 
  496.                  X(x)-(4*px/3), Y(y)+(2*py/3));
  497.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-(4*px/3), 
  498.                  X(x)+(4*px/3), Y(y)+(2*py/3));
  499.            XDrawLine(dpy,pixmap,gc, X(x)-(4*px/3), Y(y)+(2*py/3), 
  500.                  X(x)+(4*px/3), Y(y)+(2*py/3));
  501.            XDrawLine(dpy,pixmap,gc, X(x), Y(y), X(x), Y(y));
  502.            break;
  503.            case 6: /* do star */ 
  504.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y), X(x)+px, Y(y));
  505.            XDrawLine(dpy,pixmap,gc, X(x), Y(y)-py, X(x), Y(y)+py);
  506.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)-py, X(x)+px, Y(y)+py);
  507.            XDrawLine(dpy,pixmap,gc, X(x)-px, Y(y)+py, X(x)+px, Y(y)-py);
  508.            break;
  509.            }
  510.         if (type != LineSolid || width != 0) {  /* select solid line */
  511.            XSetLineAttributes(dpy, gc, width, type, CapButt, JoinBevel);
  512.            }
  513.         }
  514.      }
  515.       }
  516.  
  517.    /* trigger exposure of background pixmap */
  518.    XClearWindow(dpy,win);
  519.    XFlush(dpy);
  520.    }
  521.  
  522. /*-----------------------------------------------------------------------------
  523.  *   resize - rescale last plot if window resized
  524.  *---------------------------------------------------------------------------*/
  525.  
  526. resize(xce) XConfigureEvent *xce; {
  527.    int w = xce->width, h = xce->height;
  528.    
  529.    if (w>1 && h>1 && (w != W || h != H)) {
  530.       W = w; H = h;
  531.       display();
  532.       }
  533.    }
  534.  
  535.  
  536. /*-----------------------------------------------------------------------------
  537.  *   preset - determine options, open display, create window
  538.  *---------------------------------------------------------------------------*/
  539.  
  540. #define On(v) ( !strcmp(v,"on") || !strcmp(v,"true") || \
  541.         !strcmp(v,"On") || !strcmp(v,"True") )
  542.  
  543. #define AppDefDir "/usr/lib/X11/app-defaults"
  544. #ifndef MAXHOSTNAMELEN
  545. #define MAXHOSTNAMELEN 64
  546. #endif
  547.  
  548. static XrmDatabase dbCmd, dbApp, dbDef, dbEnv, db = (XrmDatabase)0;
  549.  
  550. char *pr_GetR(), *getenv(), *type[20];
  551. XrmValue value;
  552.  
  553. #define Nopt 27
  554. static XrmOptionDescRec options[] = {
  555.    {"-mono",             ".mono",             XrmoptionNoArg,   "on" },
  556.    {"-gray",             ".gray",             XrmoptionNoArg,   "on" },
  557.    {"-clear",            ".clear",            XrmoptionNoArg,   "on" },
  558.    {"-tvtwm",            ".tvtwm",            XrmoptionNoArg,   "on" },
  559.    {"-pointsize",        ".pointsize",        XrmoptionSepArg,  NULL },
  560.    {"-display",          ".display",          XrmoptionSepArg,  NULL },
  561.    {"-name",             ".name",             XrmoptionSepArg,  NULL },
  562.    {"-geometry",         "*geometry",         XrmoptionSepArg,  NULL },
  563.    {"-background",       "*background",       XrmoptionSepArg,  NULL },
  564.    {"-bg",               "*background",       XrmoptionSepArg,  NULL },
  565.    {"-foreground",       "*foreground",       XrmoptionSepArg,  NULL },
  566.    {"-fg",               "*foreground",       XrmoptionSepArg,  NULL },
  567.    {"-bordercolor",      "*bordercolor",      XrmoptionSepArg,  NULL },
  568.    {"-bd",               "*bordercolor",      XrmoptionSepArg,  NULL },
  569.    {"-borderwidth",      ".borderwidth",      XrmoptionSepArg,  NULL },
  570.    {"-bw",               ".borderwidth",      XrmoptionSepArg,  NULL },
  571.    {"-font",             "*font",             XrmoptionSepArg,  NULL },
  572.    {"-fn",               "*font",             XrmoptionSepArg,  NULL },
  573.    {"-reverse",          "*reverseVideo",     XrmoptionNoArg,   "on" },
  574.    {"-rv",               "*reverseVideo",     XrmoptionNoArg,   "on" },
  575.    {"+rv",               "*reverseVideo",     XrmoptionNoArg,   "off"},
  576.    {"-iconic",           "*iconic",           XrmoptionNoArg,   "on" },
  577.    {"-synchronous",      "*synchronous",      XrmoptionNoArg,   "on" },
  578.    {"-xnllanguage",      "*xnllanguage",      XrmoptionSepArg,  NULL },
  579.    {"-selectionTimeout", "*selectionTimeout", XrmoptionSepArg,  NULL },
  580.    {"-title",            ".title",            XrmoptionSepArg,  NULL },
  581.    {"-xrm",              NULL,                XrmoptionResArg,  NULL },
  582.    };
  583.  
  584. preset(argc, argv) int argc; char *argv[]; {
  585.    int Argc = argc; char **Argv = argv;
  586.  
  587. #ifdef VMS
  588.    char *display = (char *) 0;
  589. #else
  590.    char *display = getenv("DISPLAY");
  591. #endif
  592.    char *home = getenv("HOME");
  593.    char *server_defaults, *env, buf[256];
  594.  
  595.    /*---set to ignore ^C and ^Z----------------------------------------------*/
  596.  
  597.    signal(SIGINT, SIG_IGN);
  598. #ifdef SIGTSTP
  599.    signal(SIGTSTP, SIG_IGN);
  600. #endif
  601.  
  602.    /*---prescan arguments for "-name"----------------------------------------*/
  603.  
  604.    while(++Argv, --Argc > 0) {
  605.       if (!strcmp(*Argv, "-name") && Argc > 1) {
  606.      strncpy(Name, Argv[1], 64);
  607.      strncpy(Class, Argv[1], 64);
  608.      if (Class[0] >= 'a' && Class[0] <= 'z') Class[0] -= 0x20;
  609.      }
  610.       }
  611.    Argc = argc; Argv = argv;
  612.  
  613.    /*---parse command line---------------------------------------------------*/
  614.  
  615.    XrmInitialize();
  616.    XrmParseCommand(&dbCmd, options, Nopt, Name, &Argc, Argv);
  617.    if (Argc > 1) {
  618.       fprintf(stderr, "\ngnuplot: bad option: %s\n", Argv[1]);
  619.       fprintf(stderr, "gnuplot: X11 aborted.\n");
  620.       exit(1);
  621.       }
  622.    if (pr_GetR(dbCmd, ".display")) display = value.addr;
  623.  
  624.    /*---open display---------------------------------------------------------*/
  625.  
  626.    dpy = XOpenDisplay(display); 
  627.    if (!dpy) {
  628.       fprintf(stderr, "\ngnuplot: unable to open display '%s'\n", display);
  629.       fprintf(stderr, "gnuplot: X11 aborted.\n");
  630.       exit(1);
  631.       }
  632.    scr = DefaultScreen(dpy);
  633.    vis = DefaultVisual(dpy,scr);
  634.    D = DefaultDepth(dpy,scr);
  635.    root = DefaultRootWindow(dpy);
  636.    server_defaults = XResourceManagerString(dpy);
  637.  
  638.    /*---get application defaults--(subset of Xt processing)------------------*/
  639.  
  640. #ifdef VMS
  641.    strcpy (buf, "DECW$USER_DEFAULTS:GNUPLOT_X11.INI");
  642. #else
  643.    sprintf(buf, "%s/%s", AppDefDir, "Gnuplot");
  644. #endif
  645.    dbApp = XrmGetFileDatabase(buf);
  646.    XrmMergeDatabases(dbApp, &db);
  647.  
  648.    /*---get server or ~/.Xdefaults-------------------------------------------*/
  649.  
  650.    if (server_defaults)
  651.       dbDef = XrmGetStringDatabase(server_defaults);
  652.    else {
  653. #ifdef VMS
  654.       strcpy(buf,"DECW$USER_DEFAULTS:DECW$XDEFAULTS.DAT");
  655. #else
  656.       sprintf(buf, "%s/.Xdefaults", home);
  657. #endif
  658.       dbDef = XrmGetFileDatabase(buf);
  659.       }
  660.    XrmMergeDatabases(dbDef, &db);
  661.  
  662.    /*---get XENVIRONMENT or  ~/.Xdefaults-hostname---------------------------*/
  663.  
  664. #ifndef VMS
  665.    if (env = getenv("XENVIRONMENT")) 
  666.       dbEnv = XrmGetFileDatabase(env);
  667.    else {
  668.       char *p, host[MAXHOSTNAMELEN];
  669. #ifdef SOLARIS
  670.       if (sysinfo(SI_HOSTNAME, host, MAXHOSTNAMELEN) < 0) {
  671.          fprintf(stderr, "gnuplot: sysinfo failed. X11 aborted.\n");
  672. #else
  673.       if (gethostname(host, MAXHOSTNAMELEN) < 0) {
  674.          fprintf(stderr, "gnuplot: gethostname failed. X11 aborted.\n");
  675. #endif /* SOLARIS */
  676.      exit(1);
  677.      }
  678.       if (p = index(host, '.')) *p = '\0';
  679.       sprintf(buf, "%s/.Xdefaults-%s", home, host);
  680.       dbEnv = XrmGetFileDatabase(buf);
  681.       }
  682.    XrmMergeDatabases(dbEnv, &db);
  683. #endif   /* not VMS */
  684.  
  685.    /*---merge command line options-------------------------------------------*/
  686.  
  687.    XrmMergeDatabases(dbCmd, &db);
  688.  
  689.    /*---set geometry, font, colors, line widths, dash styles, point size-----*/
  690.  
  691.    pr_geometry();
  692.    pr_font();
  693.    pr_color();
  694.    pr_width();
  695.    pr_dashes();
  696.    pr_pointsize();
  697.  
  698.    /*---create window--------------------------------------------------------*/
  699.  
  700.    pr_window();
  701.  
  702.    } 
  703.  
  704. /*-----------------------------------------------------------------------------
  705.  *   pr_GetR - get resource from database using "-name" option (if any)
  706.  *---------------------------------------------------------------------------*/
  707.  
  708. char *
  709. pr_GetR(db, resource) XrmDatabase db; char *resource; {
  710.    char name[128], class[128], *rc;
  711.  
  712.    strcpy(name, Name); strcat(name, resource);
  713.    strcpy(class, Class); strcat(class, resource);
  714.    rc = XrmGetResource(db, name, class, type, &value)
  715.       ? (char *)value.addr 
  716.       : (char *)0;
  717.    return(rc);
  718.    }
  719.  
  720. /*-----------------------------------------------------------------------------
  721.  *   pr_color - determine color values
  722.  *---------------------------------------------------------------------------*/
  723.  
  724. char color_keys[Ncolors][30] =   { 
  725.    "background", "bordercolor", "text", "border", "axis", 
  726.    "line1", "line2", "line3",  "line4", 
  727.    "line5", "line6", "line7",  "line8" 
  728.    };
  729. char color_values[Ncolors][30] = { 
  730.    "white", "black",  "black",  "black",  "black", 
  731.    "red",   "green",  "blue",   "magenta", 
  732.    "cyan",  "sienna", "orange", "coral" 
  733.    };
  734. char gray_values[Ncolors][30] = { 
  735.    "black",   "white",  "white",  "gray50", "gray50",
  736.    "gray100", "gray60", "gray80", "gray40", 
  737.    "gray90",  "gray50", "gray70", "gray30" 
  738.    };
  739.  
  740. pr_color() {
  741.    unsigned long black = BlackPixel(dpy, scr), white = WhitePixel(dpy,scr);
  742.    char option[20], color[30], *v, *type; 
  743.    XColor xcolor;
  744.    Colormap cmap;
  745.    double intensity = -1;
  746.    int n;
  747.  
  748.    pr_GetR(db, ".mono")         && On(value.addr) && Mono++;
  749.    pr_GetR(db, ".gray")         && On(value.addr) && Gray++;
  750.    pr_GetR(db, ".reverseVideo") && On(value.addr) && Rv++;
  751.  
  752.    if (!Gray && (vis->class == GrayScale || vis->class == StaticGray)) Mono++;
  753.  
  754.    if (!Mono) {
  755.       cmap = DefaultColormap(dpy, scr);
  756.       type = (Gray) ? "Gray" : "Color";
  757.  
  758.       for (n=0; n<Ncolors; n++) {
  759.      strcpy(option, ".");
  760.      strcat(option, color_keys[n]);
  761.      (n > 1) && strcat(option, type);
  762.      v = pr_GetR(db, option) 
  763.          ? value.addr
  764.          : ((Gray) ? gray_values[n] : color_values[n]);
  765.  
  766.      if (sscanf(v,"%30[^,],%lf", color, &intensity) == 2) {
  767.         if (intensity < 0 || intensity > 1) {
  768.            fprintf(stderr, "\ngnuplot: invalid color intensity in '%s'\n",
  769.                        color);
  770.            intensity = 1;
  771.            }
  772.         }
  773.      else { 
  774.         strcpy(color, v);
  775.         intensity = 1;
  776.         }
  777.  
  778.      if (!XParseColor(dpy, cmap, color, &xcolor)) {
  779.         fprintf(stderr, "\ngnuplot: unable to parse '%s'. Using black.\n",
  780.                     color);
  781.         colors[n] = black;
  782.         }
  783.      else {
  784.         xcolor.red *= intensity;
  785.         xcolor.green *= intensity;
  786.         xcolor.blue *= intensity;
  787.         if (XAllocColor(dpy, cmap, &xcolor)) {
  788.            colors[n] = xcolor.pixel;
  789.            }
  790.         else {
  791.            fprintf(stderr, "\ngnuplot: can't allocate '%s'. Using black.\n",
  792.                         v);
  793.            colors[n] = black;
  794.            }
  795.         }
  796.      }
  797.       }
  798.    else {
  799.       colors[0] = (Rv) ? black : white ;
  800.       for (n=1; n<Ncolors; n++)  colors[n] = (Rv) ? white : black;
  801.       }
  802.    }
  803.  
  804. /*-----------------------------------------------------------------------------
  805.  *   pr_dashes - determine line dash styles 
  806.  *---------------------------------------------------------------------------*/
  807.  
  808. char dash_keys[Ndashes][10] =   { 
  809.    "border", "axis",
  810.    "line1", "line2", "line3",  "line4", "line5", "line6", "line7",  "line8" 
  811.    };
  812.  
  813. char dash_mono[Ndashes][10] =   { 
  814.    "0", "16",
  815.    "0", "42", "13",  "44", "15", "4441", "42",  "13" 
  816.    };
  817.  
  818. char dash_color[Ndashes][10] =   { 
  819.    "0", "16",
  820.    "0", "0", "0", "0", "0", "0", "0", "0" 
  821.    };
  822.  
  823. pr_dashes() {
  824.    int n, j, l, ok;
  825.    char option[20], *v; 
  826.    for (n=0; n<Ndashes; n++) {
  827.       strcpy(option, ".");
  828.       strcat(option, dash_keys[n]);
  829.       strcat(option, "Dashes");
  830.       v = pr_GetR(db, option) 
  831.       ? value.addr
  832.       : ((Mono) ? dash_mono[n] : dash_color[n]);
  833.       l = strlen(v);
  834.       if (l == 1 && *v == '0') {
  835.      dashes[n][0] = (unsigned char)0;
  836.      continue;
  837.      }
  838.       for (ok=0, j=0; j<l; j++) { v[j] >= '1' && v[j] <= '9' && ok++; }
  839.       if (ok != l || (ok != 2 && ok != 4)) {
  840.      fprintf(stderr, "gnuplot: illegal dashes value %s:%s\n", option, v);
  841.      dashes[n][0] = (unsigned char)0;
  842.      continue;
  843.      }
  844.       for(j=0; j<l; j++) {
  845.      dashes[n][j] = (unsigned char) (v[j] - '0');
  846.      }
  847.       dashes[n][l] = (unsigned char)0;
  848.       }
  849.    }
  850.  
  851. /*-----------------------------------------------------------------------------
  852.  *   pr_font - determine font          
  853.  *---------------------------------------------------------------------------*/
  854.  
  855. pr_font() {
  856.    char *fontname = pr_GetR(db, ".font");
  857.  
  858.    if (!fontname) fontname = FallbackFont;
  859.    font = XLoadQueryFont(dpy, fontname);
  860.    if (!font) {
  861.       fprintf(stderr, "\ngnuplot: can't load font '%s'\n", fontname);
  862.       fprintf(stderr, "gnuplot: using font '%s' instead.\n", FallbackFont);
  863.       font = XLoadQueryFont(dpy, FallbackFont);
  864.       if (!font) {
  865.      fprintf(stderr, "gnuplot: can't load font '%s'\n", FallbackFont);
  866.      fprintf(stderr, "gnuplot: no useable font - X11 aborted.\n");
  867.          exit(1);
  868.      }
  869.       }
  870.    vchar = font->ascent + font->descent;
  871.    }
  872.  
  873. /*-----------------------------------------------------------------------------
  874.  *   pr_geometry - determine window geometry      
  875.  *---------------------------------------------------------------------------*/
  876.  
  877. pr_geometry() {
  878.    char *geometry = pr_GetR(db, ".geometry");
  879.    int x, y, flags;
  880.    unsigned int w, h; 
  881.  
  882.    if (geometry) {
  883.       flags = XParseGeometry(geometry, &x, &y, &w, &h);
  884.       if (flags & WidthValue)  User_Size = 1, W = w;
  885.       if (flags & HeightValue) User_Size = 1, H = h;
  886.       if (flags & XValue) {
  887.          if (flags & XNegative)
  888.             x += DisplayWidth(dpy,scr) - W - BorderWidth*2;
  889.          User_Position = 1, gX = x;
  890.          }
  891.       if (flags & YValue) {
  892.          if (flags & YNegative)
  893.             y += DisplayHeight(dpy,scr) - H - BorderWidth*2;
  894.          User_Position = 1, gY = y;
  895.          }
  896.       }
  897.    }
  898.  
  899. /*-----------------------------------------------------------------------------
  900.  *   pr_pointsize - determine size of points for 'points' plotting style
  901.  *---------------------------------------------------------------------------*/
  902.  
  903. pr_pointsize() {
  904.    char *p = pr_GetR(db, ".pointsize") ? value.addr : "1.0" ;
  905.  
  906.    if (sscanf(p,"%lf", &pointsize) == 1) {
  907.       if (pointsize <= 0 || pointsize > 10) {
  908.      fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", p);
  909.      pointsize = 1;
  910.      }
  911.       }
  912.    else { 
  913.       fprintf(stderr, "\ngnuplot: invalid pointsize '%s'\n", p);
  914.       pointsize = 1;
  915.       }
  916.    }
  917.  
  918. /*-----------------------------------------------------------------------------
  919.  *   pr_width - determine line width values
  920.  *---------------------------------------------------------------------------*/
  921.  
  922. char width_keys[Nwidths][30] =   { 
  923.    "border", "axis",
  924.    "line1", "line2", "line3",  "line4", "line5", "line6", "line7",  "line8" 
  925.    };
  926.  
  927. pr_width() {
  928.    int n;
  929.    char option[20], *v; 
  930.    for (n=0; n<Nwidths; n++) {
  931.       strcpy(option, ".");
  932.       strcat(option, width_keys[n]);
  933.       strcat(option, "Width");
  934.       if (v = pr_GetR(db, option)) {
  935.      if ( *v < '0' || *v > '4' || strlen(v) > 1)
  936.         fprintf(stderr, "gnuplot: illegal width value %s:%s\n", option, v);
  937.      else 
  938.         widths[n] = (unsigned int)atoi(v);
  939.      }
  940.       }
  941.    }
  942.  
  943. /*-----------------------------------------------------------------------------
  944.  *   pr_window - create window 
  945.  *---------------------------------------------------------------------------*/
  946.  
  947. pr_window() {
  948.    char *title =  pr_GetR(db, ".title");
  949.    static XSizeHints hints;
  950.    int Tvtwm = 0;
  951.  
  952.    win = XCreateSimpleWindow(dpy, root, gX, gY, W, H, BorderWidth,
  953.                              colors[1], colors[0]);
  954.  
  955.    pr_GetR(db, ".clear") && On(value.addr) && Clear++;
  956.    pr_GetR(db, ".tvtwm") && On(value.addr) && Tvtwm++;
  957.  
  958.    if (!Tvtwm) {
  959.       hints.flags = (User_Position ? USPosition : PPosition);
  960.       hints.flags |= (User_Size ? USSize : PSize);
  961.       }
  962.    else {
  963.       hints.flags = PPosition;
  964.       }
  965.    hints.x = gX; hints.y = gY;        
  966.    hints.width = W; hints.height = H;
  967.  
  968.    XSetNormalHints(dpy, win, &hints);
  969.  
  970.    if (pr_GetR(db, ".iconic") && On(value.addr)) {
  971.       XWMHints wmh;
  972.  
  973.       wmh.flags = StateHint ;
  974.       wmh.initial_state = IconicState;
  975.       XSetWMHints(dpy, win, &wmh);
  976.       } 
  977.  
  978.    XStoreName(dpy, win, ((title) ? title : Class));
  979.  
  980.    XSelectInput(dpy, win, StructureNotifyMask);
  981.    XMapWindow(dpy, win);
  982.    
  983.    }
  984.